#ifndef __HANDLER_POLL_HEADER
#define __HANDLER_POLL_HEADER

#include <semaphore.h>
#include <pthread.h>
#include <vector>
#include <queue>
#include <cstdio>

#define ERR_HP_STOP 1

template<class Handler, class Task>
class HandlerPoll {
public:
	typedef key_t 			msg_key;
	typedef sem_t 			sem;
	typedef pthread_mutex_t mutex;
	typedef pthread_t 		pthread;
	typedef unsigned int 	uint;

private:
	struct ThreadArgs {
		HandlerPoll<Handler, Task> *hp;
		uint handler_id;
		ThreadArgs(HandlerPoll<Handler, Task> *ptr, uint id): 
			hp(ptr), handler_id(id) {}
		~ThreadArgs() {}
	};

private:
	uint n_handler;			//句柄数量（账号数量）
	const uint que_cap;		//任务队列容量
	sem wait_task;			//任务队列中等待处理的任务
	sem idle_place;			//任务队列的空闲位置
	mutex que_mutex;		//任务队列的互斥锁
	
	pthread 				*thread_id;
	std::vector<Handler*> 	handler;
	std::queue<Task>		task_que;
	
	const int msg_id;		// 与日志进程通信的消息队列id
	mutex out_pipe_mutex;	// 由句柄池初始化，句柄使用

	mutex py_parser_mutex;	// html_parser调用py脚本完成，需要锁

private:
	//线程函数
	static void *thread_func(void *args);
	
public:
	//句柄数，任务队列容量，句柄与统计进程间的msg_key，与日志进程间的msg_key，cookie路径
	HandlerPoll(int n, uint cap, int out_pipe, int msgid, const char *cookie_dir);
	~HandlerPoll();
	//启动句柄池，0启动成功，正数为错误代码
	int start();
	//往句柄池添加任务
	int add_task(Task task);
};

template<class Handler, class Task>
HandlerPoll<Handler, Task>::HandlerPoll(int n, uint cap, int out_pipe, 
		int msgid, const char *cookie_dir): 
		n_handler(n), que_cap(cap), msg_id(msgid) {
	sem_init(&wait_task, 0, 0);
	sem_init(&idle_place, 0, cap);
	pthread_mutex_init(&que_mutex, NULL);	
	pthread_mutex_init(&out_pipe_mutex, NULL);
	pthread_mutex_init(&py_parser_mutex, NULL);

	for (int i = 0; i < n; i++) {
		handler.push_back(new Handler(i, cookie_dir, out_pipe, msgid, &out_pipe_mutex));
	}

}

template<class Handler, class Task>
HandlerPoll<Handler, Task>::~HandlerPoll() {
	for(int i = 0; i < n_handler; i++)
		delete handler[i];
	handler.clear();
	sem_destroy(&wait_task);
	sem_destroy(&idle_place);
	pthread_mutex_destroy(&que_mutex);
	pthread_mutex_destroy(&out_pipe_mutex);
	pthread_mutex_destroy(&py_parser_mutex);
}

template<class Handler, class Task>
void* HandlerPoll<Handler, Task>::thread_func(void *arg) {
	ThreadArgs *targ = (ThreadArgs *)arg; 
	HandlerPoll<Handler, Task> *hp = targ->hp;
	uint hid = targ->handler_id;
	//delete targ;

	while(true) {
		//-----------------------------------------------------//
		sem_wait(&hp->wait_task);
		pthread_mutex_lock(&hp->que_mutex);

		//printf("thread_func get task: handler_id: %u\n", hid);
		Task task = hp->task_que.front();
		hp->task_que.pop();
		
		sem_post(&hp->idle_place);
		pthread_mutex_unlock(&hp->que_mutex);
		//-----------------------------------------------------//
		
		//printf("thread_func login and submit: handler_id: %u\n", hid);
		char user_id[10];
		char passwd[10];
		sprintf(user_id, "gvj%d", hid);
		sprintf(passwd, "gvj2014");
		hp->handler[hid]->login(user_id, passwd, NULL);
		hp->handler[hid]->submit(task);

		pthread_mutex_lock(&hp->py_parser_mutex);
		hp->handler[hid]->get_judge_result();
		pthread_mutex_unlock(&hp->py_parser_mutex);

		hp->handler[hid]->send_result_to_listen();
	}
	return NULL;
}

template<class Handler, class Task>
int HandlerPoll<Handler, Task>::add_task(Task task) {
	sem_wait(&idle_place);
	pthread_mutex_lock(&que_mutex);

	task_que.push(task);
	//printf("handler_poll: static func: add_task\n");

	sem_post(&wait_task);
	pthread_mutex_unlock(&que_mutex);
	return 0;
}

template<class Handler, class Task>
int HandlerPoll<Handler, Task>::start() {
	pthread_mutex_lock(&que_mutex);
	thread_id = new pthread[n_handler];
	for (int i = 0; i < n_handler; i++) {
		ThreadArgs *targ = new ThreadArgs(this, i);
		int res = pthread_create(&thread_id[i], NULL, thread_func, (void*)targ);
		//printf("(%d)handler_poll: pthread_create: %d\n", i , res);
	}
	pthread_mutex_unlock(&que_mutex);
	return 0;
}

#endif // __HANDLER_POLL_HEADER
